test = "Hello World"
print("test: "+test)

#使用math定义sigmoid函数===========================

import math

def basic_sigmoid(x):
    """
    计算x的sigmoid。
    参数：
        x--标量
    返回：
        s--sigmoid（x） 
    """
    s = 1/(1 + math.exp(-x))
    
    return s

print(basic_sigmoid(3))
# ===================================================
import numpy as np

# np.exp的例子,结果会是（exp(1),exp(2),exp(3)
x = np.array([1,2,3])
print(np.exp(x))

# 向量运算的例子
x = np.array([1, 2, 3])
print (x + 3)

# 使用numpy实现sigmoid函数============================
import numpy as np

def  sigmoid(x):
    """
    计算x参数的sigmoid:
    x——任意大小的标量或numpy数组返回：
    s——sigmoid（x）
    """
    s = 1/(1+np.exp(-x))

    return s

# 验证
x = np.array([1,2,3])
print(sigmoid(x))

# 编写sigmoid的梯度==================================
def sigmoid_derivative(x):
    """
    计算sigmoid函数相对于其输入x的梯度（也称为斜率或导数）。
    您可以将sigmoid函数的输出存储到变量中，然后使用它来计算梯度。
    参数：
        x——标量或numpy数组返回：
        ds——计算的梯度。
    """
    s = sigmoid(x)
    ds = s*(1-s)

    return ds
# 验证
x = np.array([1,2,3])
print("sigmoid_derivative(x) = "+str(sigmoid_derivative(x)))

# 实现image2vector() ,该输入采用维度为(length, height, 3)的输入，并返回维度为(length*height*3, 1)的向量。=====
def image2vector(image):
    """
    参数：
        image--形状的numpy数组（长度、高度、深度）
    返回：
        v--形状的向量（长度*高度*深度，1）
    """
# x.shape用于获取矩阵/向量的维度，
# x.reshape用于将x重塑为其他尺寸
    v = image.reshape(image.shape[0]*image.shape[1]*image.shape[2],1)

    return v

# 验证
image = np.array([[[ 0.67826139,  0.29380381],
            [ 0.90714982,  0.52835647],
            [ 0.4215251 ,  0.45017551]],

        [[ 0.92814219,  0.96677647],
            [ 0.85304703,  0.52351845],
            [ 0.19981397,  0.27417313]],

        [[ 0.60659855,  0.00533165],
            [ 0.10820313,  0.49978937],
            [ 0.34144279,  0.94630077]]])

print("image2vector(image) = \n"+str(image2vector(image)))

# 行标准化/归一化（将x的每个行向量除以其范数）=======================================
def normalizeRows(x):
    """
    实现一个函数，用于规范化矩阵x的每一行（使其具有单位长度）。
    参数：
        x——形状为（n，m）的numpy矩阵
    返回：
        x——规格化（按行）numpy矩阵。允许您修改x。
    """
# 取范数：x为矩阵，axis（0，1，none默认，0代表按列处理，1代表按行处理），keepdims(是否保持维数)
    x_norm = np.linalg.norm(x,axis = 1,keepdims= True)
    x = x/x_norm

    return x
# 验证
x = np.array([
    [0, 3, 4],
    [1, 6, 4]])
print("normalizeRows(x) = \n" + str(normalizeRows(x)))

# 实现softmax函数，可理解为算法需要对两个或多个类进行分类时使用的标准化函数=========================
def softmax(x):
    """
    计算输入x的每一行的softmax。
    您的代码应该适用于行向量和形状矩阵（n，m）。
    参数：
        x--形状（n，m）的numpy矩阵
    返回：
        s--一个numpy矩阵，等于形状（n，m）的x的softmax 
    """
    x_exp = np.exp(x)
    x_sum = np.sum(x_exp, axis = 1, keepdims = True)
    s = x_exp / x_sum

    return s
# 验证
x = np.array([
    [9, 2, 5, 0, 0],
    [7, 5, 0, 0 ,0]])
print("softmax(x) = \n" + str(softmax(x)))

x1 = [9, 2, 5, 0, 0, 7, 5, 0, 0, 0, 9, 2, 5, 0, 0]
x2 = [9, 2, 2, 9, 0, 9, 2, 5, 0, 0, 9, 2, 5, 0, 0]

### 向量的矢量点积 ###
import time

tic = time.process_time()
dot = np.dot(x1,x2)
toc = time.process_time()
print ("dot = " + str(dot) + "\n ----- Computation time = " + str(1000*(toc - tic)) + "ms")

### 向量化外积###
tic = time.process_time()
outer = np.outer(x1,x2)
toc = time.process_time()
print ("outer = " + str(outer) + "\n ----- Computation time = " + str(1000*(toc - tic)) + "ms")

### 矢量化元素乘法 ###
tic = time.process_time()
mul = np.multiply(x1,x2)
toc = time.process_time()
print ("elementwise multiplication = " + str(mul) + "\n ----- Computation time = " + str(1000*(toc - tic)) + "ms")

### 矢量化广义点积 ###
W = np.random.rand(3,len(x1)) # Random 3*len(x1) numpy array
tic = time.process_time()
dot = np.dot(W,x1)
toc = time.process_time()
print ("gdot = " + str(dot) + "\n ----- Computation time = " + str(1000*(toc - tic)) + "ms")

# 实现L1和L2的损失函数===================================================================================
def L1(yhat,y):
    """
    参数：
        yhat—大小为m的向量（预测标签）y—大小为m的向量（真标签）
    返回：
        loss—上面定义的L1 loss函数的值
    """
    loss = np.sum(np.abs(y-yhat))

    return loss
# 验证
yhat = np.array([.9, 0.2, 0.1, .4, .9])
y = np.array([1, 0, 0, 1, 1])
print("L1 = " + str(L1(yhat,y)))


def L2(yhat,y):
    """
    参数：
        yhat—大小为m的向量（预测标签）y—大小为m的向量（真标签）
    返回：
        loss—上面定义的L1 loss函数的值
    """
    loss = np.dot((y-yhat),(y-yhat).T)

    return loss

# 验证
yhat = np.array([.9, 0.2, 0.1, .4, .9])
y = np.array([1, 0, 0, 1, 1])
print("L2 = " + str(L2(yhat,y)))